Oculus Quest2 でのURP利用不具合対応まとめ

March 04, 2023


不具合情報 & 対応状況 まとめ

URP + Oculus2 での開発で描画周りでかなりハマってしまったのでメモを残します。

シングルパスインスタンシングを利用する場合URP2021以降はShaderを書き換える必要がある

ポストエフェクトShaderをXR用にカスタマイズする時、 Unity2021(URP12), Unity 2022 (URP14) では XR で Command.Blit は利用できません (シングルパスインスタンシング利用時)

どうもcmd.blitを利用すると内部でシングルパスインスタンシング用のキーワードの有効/無効の切り替えがおかしくなるようです

Reference https://docs.unity3d.com/ja/Packages/com.unity.render-pipelines.universal@14.0/manual/renderer-features/how-to-fullscreen-blit-in-xr-spi.html

URP14の場合

Cmd.Blit を以下に変換する必要があります。

  • Blitter.BlitCameraTexture(cmd, _renderer.cameraColorTarget, RTHandle);
  • ScriptableRenderPassが持つ Blit メソッド

Blitter と呼ばれる専用のクラスのBlitを利用、またはPassが持つBlitメソッドを利用します(内部でBlitterを利用している)

RenderTargetIdentifierは非推奨となっているためすべて RTHandle に変換します。 GetTemporaryRT は

RenderingUtils.ReAllocateIfNeeded

メソッドに変更します。

Shader内部でBlitしたテクスチャを参照する場合

// 追加
#include "Packages/com.unity.render-pipelines.core/Runtime/Utilities/Blit.hlsl"

...

// フラグメントシェーダー内部
SAMPLE_TEXTURE2D_X(_BlitTexture, sampler_LinearRepeat, IN.uv);

のように _BlitTexture で参照します。 _BlitTextureは Blit 時に指定されています

public static void BlitTexture(CommandBuffer cmd, RTHandle source, Vector4 scaleBias, Material material, int pass)
{
    s_PropertyBlock.SetVector(BlitShaderIDs._BlitScaleBias, scaleBias);
    s_PropertyBlock.SetTexture(BlitShaderIDs._BlitTexture, source);
    DrawTriangle(cmd, material, pass);
}

URP12 の場合

また、Unity2021 LTS (URP12) ではcameraColorTargetのRTHandleが取得できません。なのでURP12用の対応をする必要があります。 そのため、 Cmd.Blit を以下に変換する必要があります

// カメラが写しているもの
var source = renderingData.cameraData.renderer.cameraColorTarget;

// _blitMaterial は URP の中にある
// "Hidden/Universal Render Pipeline/Blit"
// Shaderから生成したマテリアルです。一時的なRTにBlitするために利用します

// XR 利用するか?で分岐する必要がある
if (renderingData.cameraData.xrRendering)
{
		// Blit する場合は 以下の形を取る。

		// MipLevel, DepthはOffにする
		cmd.SetRenderTarget(new RenderTargetIdentifier(tempCopy, 0, CubemapFace.Unknown, -1), RenderBufferLoadAction.Load, RenderBufferStoreAction.Store);
		
		// Blit専用のMaterialを利用してBlitする。独自のShaderでBlitしたい場合はここを変更
		cmd.SetGlobalTexture("_SourceTex", source);
		cmd.DrawProcedural(Matrix4x4.identity, _blitMaterial, 0, MeshTopology.Quads, 4, 1, null);

}
else
{
	  // MultiPassの場合はコレでも問題ない 
		cmd.Blit(source, tempCopy);
}

また、URP14, 12共通でShaderの方は以下のようにします ※ 以下はまだ調査中のため、調査結果によって修正します

/ 追加
#include "Packages/com.unity.render-pipelines.core/Runtime/Utilities/Blit.hlsl"

...

// 頂点シェーダー用の入力
struct Attributes
{
    float4 positionOS       : POSITION;
    float2 uv               : TEXCOORD0;
    uint vertexID : SV_VertexID; // 追加
    UNITY_VERTEX_INPUT_INSTANCE_ID
};

...

varyings Vertex(Attributes i)
{

//    float4 pos = input.positionOS;
//    float2 uv  = input.uv;
    float4 pos = GetFullScreenTriangleVertexPosition(input.vertexID); // 追加
    float2 uv  = GetFullScreenTriangleTexCoord(input.vertexID); // 追加
}

上記はMultiView, シングルパスインスタンシング利用時の対応のため、もしMultiPassを利用する場合は変換しなくて問題ありません。

URP12は分岐を書く必要がありかなり対応が難しい(めんどくさい)です…

Unity2022利用時にOculusでクラッシュする

これは設定の問題かもしれませんがUnity2022でのみ発生し解決方法が不明です.. そのため、プロジェクトを Unity2022 → Unity2021 にロールバックしました

Unity2022 + URP14 で以下の条件でクラッシュしました

  • VideoPlayer再生 + 独自 PostProcess 利用時に約10秒後にクラッシュする

Valkan、OpenGLES3 両方での発生。 PostEffectを通さないようにすると発生しなくなりました。なので原因となるポイントは特定できたのですがどのように対応して修正すればよいかが全くわかりません…

正直不具合の匂いがするため安定するバージョンが出るのを待つためにUnityを2021に戻しました。 ちなみにEditorではクラッシュなどの不具合は発生しません

Unity2021(URP12)でValkanを利用するとPostProcessが正常に映らない

Unity2021でPostProcess対応した時、それを有効にすると画面が真っ暗になる不具合が発生しました

原因がつかめず試行錯誤した結果、ValkanからOpenGLES3にAPIを変更すると問題なくなりました Valkan対応はOculusもまだ実験段階ということですが…

https://www.google.com/search?q=valkan+oculus&rlz=1C1TKQJ_jaJP1016JP1016&oq=valkan+oculus&aqs=chrome..69i57j35i39l2j0i10i512l4j69i61.2938j0j4&sourceid=chrome&ie=UTF-8

特にパフォーマンスをギリギリ攻めるプロジェクトではないためOpenGLES3で様子を見ることにしました。

※ Shaderの書き方の問題かもしれないためこちらは優先的に調査しています

起動直後黒い画面になり CenterEyeAnchor が描画されない

起動直後Oculus の CenterEyeAnchor がもつCameraが描画されませんでした コントローラーを画面外に持っていったりカメラを反対方向に動かしたり刺激を与えると描画されるようになる謎の現象となります

以下Forumにある通り Universal Render Pipeleine Asset の Opaque Texture をOFFにすると現象は起きなくなりました

https://forum.unity.com/threads/lwrp-ui-not-displayed-on-oculus-quest.697922/

04299220906337003087B0A512EC4E16

URP + OpenGL ES3 + MultiView の利用時に発生するかもしれません…

もしかしたら描画順によるものかもしれませんが起動時のタイトル画面ではPostEffectなど特殊な描画はしていないためURPの不具合を疑っていますが..

最後に

URP12, 14 ともに XR の利用では未だに不具合報告、議論がされています 個人的な感想として、シングルパスインスタンシングの対応をする場合 URP14 のほうが楽ですが、不具合が取り切れていないため無難に Unity2021, URP12 での対応が良い気がします。 また、パフォーマンスを犠牲にするならMultiPassで進めるのが、RendererやShaderを書き換えもせずによくなるため一番楽です。

また今回調査で参考になりましたForumを載せていますのでご参考ください 個人的にも随時追っていき、今後のアップデートで修正や変更があった場合は更新していきます

参考

https://forum.unity.com/threads/commandbuffer-blit-in-vr-xr.1204489/

https://forum.unity.com/threads/how-to-blit-in-urp-documentation-and-or-a-unity-blog-post-on-what-every-blit-function-does.1211508/#post-7735527

以下Unity2022以降での不具合Forum情報のまとめ • https://issuetracker.unity3d.com/issues/meta-quest-performance-loss-between-urp-versions-when-builthttps://issuetracker.unity3d.com/issues/quest-2-build-crashes-on-quest-2-when-graphics-jobs-are-enabledhttps://issuetracker.unity3d.com/issues/quest-2-build-crashes-on-quest-2-when-graphics-jobs-are-enabled